<template>
  <div ref="canvas"></div>
</template>

<script lang="ts" setup>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import Stats from "three/examples/jsm/libs/stats.module";
import {ref, onMounted, render} from "vue";
import {addLargeGroundPlane, initDefaultLighting} from "@/book/ThreeUtils";

// 画布
const canvas = ref<any>();
// 场景
const scene = new THREE.Scene();
// 渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x000000);
renderer.setPixelRatio(window.devicePixelRatio);
// 相机
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 2000);
camera.position.set(-30, 40, 30);
camera.lookAt(0, 0, 0,);
// 相机控件
const orbitControl = new OrbitControls(camera, renderer.domElement);
// 性能统计
const stat = Stats();
// 光源
initDefaultLighting(scene, undefined);
// 地板
addLargeGroundPlane(scene, true);
// point
const points = [];
for (let i = 0; i < 8; i++) {
  var randomX = -20 + Math.round(Math.random() * 50);
  var randomY = -15 + Math.round(Math.random() * 40);
  var randomZ = -20 + Math.round(Math.random() * 40);

  points.push(new THREE.Vector3(randomX, randomY, randomZ));
}
const pointGroup = new THREE.Group();
const pointMaterial = new THREE.MeshBasicMaterial({
  color: 0xff0000,
  transparent: false,
});
points.forEach( (p) => {
  const geom = new THREE.SphereGeometry(0.2);
  const mesh = new THREE.Mesh(geom, pointMaterial);
  mesh.position.copy(p);
  pointGroup.add(mesh);
});
scene.add(pointGroup);
// tube
const tubeGeometry = new THREE.TubeGeometry(new THREE.CatmullRomCurve3(points));
const tubeMaterial = new THREE.MeshStandardMaterial({
  color: 0xff0000,
  side: THREE.DoubleSide,
});
const tube = new THREE.Mesh(tubeGeometry, tubeMaterial);
scene.add(tube);

let step = 0;


const render = () => {
  stat.update();
  orbitControl.update();

  step += 0.005;

  tube.rotation.y = step;
  tube.rotation.x = step;
  tube.rotation.z = step;

  if (pointGroup) {
    pointGroup.rotation.y = step;
    pointGroup.rotation.x = step;
    pointGroup.rotation.z = step;
  }

  requestAnimationFrame(render);
  renderer.render(scene, camera);
};

onMounted(() => {
  canvas.value.appendChild(stat.domElement);
  canvas.value.appendChild(renderer.domElement);

  render();
});

</script>
